﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	EntityFacadeQueryExecutor.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System.Collections.Generic;
using System.Diagnostics;

namespace Smart.Common.Entities
{
	/// <summary>
	/// EntityFacade query executor
	/// </summary>
	[DebuggerStepThrough]
	public class EntityFacadeQueryExecutor<TEntityType> : IEntityFacadeQueryExecutor<TEntityType>
		where TEntityType : Entity
	{
		/// <summary>
		/// Facade
		/// </summary>
		public EntityFacade<TEntityType> Facade { get; protected set; }

		/// <summary>
		/// Query builder
		/// </summary>
		public IQueryBuilder<IEntityFacadeQueryExecutor<TEntityType>> Query { get; set; }

		/// <summary>
		/// Execute query and return list of entities
		/// </summary>
		public virtual IEntityList<TEntityType> Execute()
		{
			return Execute(1000000);
		}

		/// <summary>
		/// Execute query and return list of entities
		/// </summary>
		public virtual IEntityList<TEntityType> Execute(int rowLimit)
		{
			var query = Query == null ? null : Query.FormatQuery();
			var props = Query == null ? null : Query.GetProperties();

			return Execute(query, rowLimit, props);
		}

		/// <summary>
		/// Execute query and return list of entities
		/// </summary>
		public virtual IEntityList<TEntityType> Execute(IQueryBuilder builder, int rowLimit)
		{
			var query = builder == null ? null : builder.FormatQuery();
			var props = builder == null ? null : builder.GetProperties();

			return Execute(query, rowLimit, props);
		}

		/// <summary>
		/// Execute query and return list of entities
		/// </summary>
		public virtual IEntityList<TEntityType> Execute(string query, int rowLimit)
		{
			return Execute(query, rowLimit, null);
		}

		/// <summary>
		/// Execute query and return only one first entity
		/// </summary>
		public virtual TEntityType ExecuteOne()
		{
			var res = Execute(1);

			return res.Count < 1 ? null : res[0];
		}

		/// <summary>
		/// Executes query
		/// </summary>
		protected virtual IEntityList<TEntityType> Execute(string query, int rowLimit, Dictionary<string, object> properties)
		{
			var mi = Facade.MappingInfo;

			return
				mi.UseCache
					? Facade.Service.LoadEntities(query, rowLimit, properties,
												  Facade.Name.ToLower().GetHashCodeX(),
												  mi.CacheUserDependent, false,
												  mi.CacheAbsoluteTimeout, mi.CacheSlidingExpiration, mi.CachePriority)
					: Facade.Service.LoadEntities(query, rowLimit, properties);
		}

		/// <summary>
		/// EntityFacade query executor
		/// </summary>
		public EntityFacadeQueryExecutor(EntityFacade<TEntityType> facade)
		{
			Facade = facade;
		}
	}
}